package smartrpc.boot.starter.component;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import smart.rpc.server.ServerServiceContainer;
import smart.rpc.server.SmartRPCServerApplication;
import smartrpc.boot.starter.config.SmartRPCProperties;

import javax.annotation.PostConstruct;
import java.util.Map;

/**
 * Created By gao_e on 2020/3/7 21:39
 * IOC容器加载完毕后，初始化启动 RPC SERVER
 */
@Component
@EnableConfigurationProperties({SmartRPCProperties.class})
@ConditionalOnProperty(
        prefix = "rpcserver",
        name = "openSmartRPCServer",
        havingValue = "true"
)
// 只有在 当前服务不属于web服务 的情况下，才能作为RPC-Server服务启动
// web服务应该属于RPC客户端,而非RPC服务提供者
@ConditionalOnMissingBean(value = ServletWebServerFactory.class)
public class SmartRPCServerInit implements InitializingBean {

    @Autowired
    private SmartRPCProperties smartRPCProperties;
    @Autowired
    private ApplicationContext applicationContext;

    @PostConstruct
    public void log() {
        System.out.println("已经加载完Smart RPC Server端相关自动配置");
        System.out.println("SmartRPCProperties = " + smartRPCProperties);
    }

    /**
     * @throws Exception
     * IOC容器加载完成触发RPC-SERVER启动
     */
    @Override
    public void afterPropertiesSet() throws Exception {

        System.out.println("开始准备启动RPC SERVER...");

        // 这里使用的是spring提供的@service注解
        // 提供远程RPC访问实现了开放接口服务的具体service类需要使用Spring提供的@Service注解
        // 从IOC容器中获取spring管理的所有service对象实例, ——> K:serviceName,V:serviceBean
        Map<String, Object> serviceBeanMap = applicationContext.getBeansWithAnnotation(Service.class);

        // 将我们IOC中的实例(引用)拷贝到 RPC Server端service容器中
        // 以方便RPC Server端收到请求后，可以直接取用(跟IOC中是同一个对象)，然后利用反射执行
        ServerServiceContainer.addAllService(serviceBeanMap);

        // 构建参数,调用Smart-RPC-Server启动程序
        String[] args = new String[2];
        args[0] = "port=" + smartRPCProperties.getSmartRPCServerPort();
        args[1] = "registHost=" + smartRPCProperties.getRegistHost();

        // 启动 rpc server 端
        SmartRPCServerApplication.start(args);
    }
}
